/****************************************************************************
 *
 *  3DSVERS.C
 *
 *  (C) Copyright 1997 by Autodesk, Inc.
 *
 *  This program is copyrighted by Autodesk, Inc. and is licensed to you under
 *  the following conditions.  You may not distribute or publish the source
 *  code of this program in any form.  You may incorporate this code in object
 *  form in derivative works provided such derivative works are (i.) are de-
 *  signed and intended to work solely with Autodesk, Inc. products, and (ii.)
 *  contain Autodesk's copyright notice "(C) Copyright 1995 by Autodesk, Inc."
 *
 *  AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.  AUTODESK SPE-
 *  CIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
 *  A PARTICULAR USE.  AUTODESK, INC.  DOES NOT WARRANT THAT THE OPERATION OF
 *  THE PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE.
 *
 ***************************************************************************/

/* Module Overview:
   3dsvers.c, 3DSVERS.H - File Release related functions.
   
*/

#include <stdio.h>
#include <string.h>
#include "3DSTYPE.H"
#include "DBASE3DS.H"
#include "3DSPRIM.H"
#include "CHUNKINF.H"
#include "CHUNK3DS.H"
#include "3DSFTKST.H"
#include "3DSVERS.H"
#include "3DSERR.H"

/* Scans the database for M3D_VERSION chunk and returnes its release */
releaselevel3ds GetM3dMagicRelease3ds(database3ds *db)
{
   chunk3ds *c = NULL;

   if (db == NULL)
      ADD_ERROR_RETURNR(ERR_INVALID_ARG, ReleaseNotKnown3ds);

   if (db->topchunk == NULL)
      ADD_ERROR_RETURNR(ERR_INVALID_DATABASE, ReleaseNotKnown3ds);
   
   /* If the database is a 3DS file */
   if (db->topchunk->tag == M3DMAGIC)
   {
      FindChunk3ds(db->topchunk, M3D_VERSION, &c);

      if (c != NULL)
      {
	 M3dVersion *d;
	 d = ReadChunkData3ds(c);

	 if (d->version == 1) return Release13ds;
	 else
	    if (d->version == 2) return Release23ds;
	    else
	       if (d->version == 3) return Release33ds;
	       else
		  return ReleaseNotKnown3ds;
      }
      else
	 return ReleaseNotKnown3ds;
   }
   else
      return ReleaseNotKnown3ds;
}

/* Sets the M3dMagicRelease level */
void PutM3dMagicRelease3ds(database3ds *db, releaselevel3ds release)
{

   if (db == NULL)
      SET_ERROR_RETURN(ERR_INVALID_ARG);
   if (db->topchunk == NULL)
      SET_ERROR_RETURN(ERR_INVALID_DATA);

   if (db->topchunk->tag == M3DMAGIC)
   {
      chunk3ds *c;
      M3dVersion *d;

      ReplaceOrAddChild3ds(db->topchunk, M3D_VERSION, &c);
      ON_ERROR_RETURN;
      d = InitChunkData3ds(c);
      ON_ERROR_RETURN;

      switch(release)
      {
      case Release13ds:
	 d->version = 1;
	 break;
      case Release23ds:
	 d->version = 2;
	 break;
      case Release33ds:
	 d->version = 3;
	 break;
      case ReleaseNotKnown3ds:
	 d->version = 4;
      }
   }

}

/* Scans the database for MESH_VERSION chunk and returnes its release */
releaselevel3ds GetMeshRelease3ds(database3ds *db)
{
   chunk3ds *c = NULL;

   if (db == NULL)
      ADD_ERROR_RETURNR(ERR_INVALID_ARG, ReleaseNotKnown3ds);

   if (db->topchunk == NULL)
      ADD_ERROR_RETURNR(ERR_INVALID_DATABASE, ReleaseNotKnown3ds);
   
   /* If the database is a 3DS file */
   if ((db->topchunk->tag == M3DMAGIC || db->topchunk->tag == CMAGIC))
   {
      FindChunk3ds(db->topchunk, MESH_VERSION, &c);

      if (c != NULL)
      {
	 MeshVersion *d;
	 d = ReadChunkData3ds(c);

	 if (d->version == 1) return Release13ds;
	 else
	    if (d->version == 2) return Release23ds;
	    else
	       if (d->version == 3) return Release33ds;
	       else
		  return ReleaseNotKnown3ds;
      }
      else
	 return ReleaseNotKnown3ds;
   }
   else
       return ReleaseNotKnown3ds;
}

/* Sets the MeshRelease level */
void PutMeshRelease3ds(database3ds *db, releaselevel3ds release)
{

   if (db == NULL)
      SET_ERROR_RETURN(ERR_INVALID_ARG);
   if (db->topchunk == NULL)
      SET_ERROR_RETURN(ERR_INVALID_DATA);

   if ((db->topchunk->tag == M3DMAGIC) || (db->topchunk->tag == CMAGIC))
   {
      chunk3ds *mdata;
      chunk3ds *c;
      M3dVersion *d;


      FindChunk3ds(db->topchunk, MDATA, &mdata);

      if (mdata == NULL)
      {
	 InitChunkAs3ds(&mdata, MDATA);
	 AddChildOrdered3ds(db->topchunk, mdata);
      }
      
      ReplaceOrAddChild3ds(mdata, MESH_VERSION, &c);
      d = InitChunkData3ds(c);

      switch(release)
      {
      case Release13ds:
	 d->version = 1;
	 break;
      case Release23ds:
	 d->version = 2;
	 break;
      case Release33ds:
	 d->version = 3;
	 break;
      case ReleaseNotKnown3ds:
	 d->version = 4;
      }
   }
}

/* Scans the database for KFHDR chunk and returnes its release level */
releaselevel3ds GetKfRelease3ds(database3ds *db)
{
   chunk3ds *c = NULL, *kfdata;

   if (db == NULL)
      SET_ERROR_RETURNR(ERR_INVALID_ARG, ReleaseNotKnown3ds);
   if (db->topchunk == NULL)
      SET_ERROR_RETURNR(ERR_INVALID_DATABASE, ReleaseNotKnown3ds);

   /* If the database is a 3DS file */
   if ((db->topchunk->tag == M3DMAGIC || db->topchunk->tag == CMAGIC))
   {
      FindChunk3ds(db->topchunk, KFDATA, &kfdata);

      if (kfdata != NULL)
	 FindChunk3ds(db->topchunk, KFHDR, &c);

      if (c != NULL)
      {
	 KFHdr *d;
	 d = ReadChunkData3ds(c);

	 if (d->revision == 1) return Release13ds;
	 else
	    if (d->revision == 2) return Release23ds;
	    else
	       if (d->revision == 5) return Release33ds;
	       else
		  return ReleaseNotKnown3ds;
      }
      else
	 return ReleaseNotKnown3ds;
   }
   else
      return ReleaseNotKnown3ds;
}

/* Sets the KFDATA release level */
void PutKfRelease3ds(database3ds *db, releaselevel3ds release)
{
   KFHdr *d;

   if (db == NULL)
      SET_ERROR_RETURN(ERR_INVALID_ARG);
   if (db->topchunk == NULL)
      SET_ERROR_RETURN(ERR_INVALID_DATABASE);

   if ((db->topchunk->tag == M3DMAGIC) || (db->topchunk->tag == CMAGIC))
   {
      chunk3ds *kfdata;
      chunk3ds *kfhdr;

      /* Find the KFDATA section */
      FindChunk3ds(db->topchunk, KFDATA, &kfdata);

      /* If one doesn't exist, then create it */
      if (kfdata == NULL)
      {
	 InitChunkAs3ds(&kfdata, KFDATA);
	 AddChildOrdered3ds(db->topchunk, kfdata);
      }

      /* Find the KFHDR */
      FindChunk3ds(kfdata, KFHDR, &kfhdr);

      /* If a KFHDR doesn't exist, then create it */
      if (kfhdr == NULL)
      {

	 d = InitChunkAndData3ds(&kfhdr, KFHDR);
	 d->filename = strdup("");
	 d->animlength = 30; /* Just a default */
	 AddChildOrdered3ds(kfdata, kfhdr);
	 
      } else /* Else, just get its data */
      {
	 d = ReadChunkData3ds(kfhdr);
      }

      /* Set the revision level */
      switch(release)
      {
      case Release13ds:
	 d->revision = 1;
	 break;
      case Release23ds:
	 d->revision = 2;
	 break;
      case Release33ds:
	 d->revision = 5;
	 break;
      case ReleaseNotKnown3ds:
	 d->revision = 6;
	 break;
      }
   }
}

releaselevel3ds GetDatabaseRelease3ds(database3ds *db)
{
   dbtype3ds dtype;
   
   dtype = GetDatabaseType3ds(db);

   switch(dtype)
   {
   case MeshFile:
      return GetM3dMagicRelease3ds(db);
   case ProjectFile:
      return GetMeshRelease3ds(db);
   case MaterialFile:
      return Release33ds;
   default:
      return ReleaseNotKnown3ds;
   }
}

void PutDatabaseRelease3ds(database3ds *db, releaselevel3ds rev)
{
   dbtype3ds dtype;

   dtype = GetDatabaseType3ds(db);

   switch(dtype)
   {
   case MeshFile:
      PutM3dMagicRelease3ds(db, rev);
   case ProjectFile:
      PutMeshRelease3ds(db, rev);
      PutKfRelease3ds(db, rev);
      break;
   default:
      break;
   }
}
